package com.wson.model.compass.status.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import com.wson.adapter.clouddisk.factory.CodiskAdapterFactory;
import com.wson.adapter.codisk.ICodiskAdapter;
import com.wson.dao.entity.proton.IProtonEntityProp;
import com.wson.function.support.MailNotificationFunc;
import com.wson.function.wolfow.AddFlowFunc;
import com.wson.function.wolfow.TriggerEventFunc;
import com.wson.model.basic.IBasicView;
import com.wson.model.basic.IMarkableField;
import com.wson.model.compass.portfolio.ICompassPortfolioManip;
import com.wson.model.compass.portfolio.ICompassPortfolioMeta;
import com.wson.model.compass.portfolio.ICompassPortfolioView;
import com.wson.model.compass.status.ICompassStatusManip;
import com.wson.model.compass.status.ICompassStatusMeta;
import com.wson.model.compass.status.ICompassStatusView;
import com.wson.model.entity.impl.EntityModel;
import com.wson.model.framework.identity.IIdentityManip;
import com.wson.model.framework.identity.IIdentityMeta;
import com.wson.model.framework.identity.IIdentityView;
import com.wson.model.framework.user.IUserView;
import com.wson.model.framework.user.impl.UserModel;
import com.wson.model.wolfow.flow.IWolfFlowView;
import com.wson.model.wolfow.route.IWolfRouteManip;
import com.wson.model.wolfow.route.IWolfRouteMeta;
import com.wson.model.wolfow.route.IWolfRouteView;
import com.wson.platform.factory.impl.BeanFactory;
import com.wson.root.util.LoggerUtil;
import com.wson.util.throwable.BasicException;

public class CompassStatusModel extends EntityModel implements ICompassStatusManip, ICompassStatusView{



	
	
	@Override
	public String getSync() {
		return ICompassStatusMeta.SYNC_SELF;
	}

	@Override
	public Long getMetaID() {
		return ICompassStatusMeta.META_ID;
	}
	
	@IMarkableField(Attribute=ATTR_INBOUNDROUTEID, Syntax=SYNC_INBOUNDROUTEID
			, PropID=PROP_COMMON, PropIndex=IProtonEntityProp.PROP_VALUEINDEX_1
			, Behavior=REPLETENCY_SELECTVALUE
			, ValueType=IMarkableField.VALUETYPE_MODEL
			, ValueMeta=IWolfRouteMeta.META_ID
			, ValueCategory=IWolfRouteMeta.CATEGORY_INITIAL
			, ValueMatrix=IMarkableField.VALUEMMATRIX_ADMIN
	)
	private Long inboundRouteID;

	
	@IMarkableField(Attribute=ATTR_RETWEETEDSTATUSID, Syntax=SYNC_RETWEETEDSTATUSID
			, PropID=PROP_COMMON, PropIndex=IProtonEntityProp.PROP_VALUEINDEX_2
			, Behavior=REPLETENCY_GENERATED
	)	
	private Long retweetStatusID;
	
	@IMarkableField(Attribute=ATTR_TARGETS, Syntax=SYNC_TARGETS
			, PropID=PROP_COMMON, PropIndex=IProtonEntityProp.PROP_VALUEINDEX_8
			, Behavior=REPLETENCY_INPUTTEXT			
	)
	private String targets;
	

	@IMarkableField(Attribute=ATTR_FLOWID, Syntax=SYNC_FLOWID
			, PropID=PROP_COMMON, PropIndex=IProtonEntityProp.PROP_VALUEINDEX_3
			, Behavior=REPLETENCY_GENERATED
	)	
	private Long flowID;
	
	@IMarkableField(Attribute=ATTR_INBOUNDEVENTID, Syntax=SYNC_INBOUNDEVENTID
			, PropID=PROP_COMMON, PropIndex=IProtonEntityProp.PROP_VALUEINDEX_4
			, Behavior=REPLETENCY_GENERATED
	)		
	private Long inboundEventID;
	
	private Long inboundStepID;
	private Long outboundEventID;
	
	private ICompassStatusView retweetStatus; 
	
	@IMarkableField(Attribute=ATTR_INITIALFOLDER, Syntax=SYNC_INITIALFOLDER
			, Behavior=REPLETENCY_GENERATED
	)		
	private  String initialfolder;
	
	@IMarkableField(Attribute=ATTR_DOCUMENTSREQUIRED, Syntax=SYNC_DOCUMENTSREQUIRED
			, Behavior=REPLETENCY_GENERATED
	)
	private  Boolean documentsRequired;
	
	public Long getInboundRouteID() {
		return inboundRouteID;
	}

	public void setInboundRouteID(Long flowType) {
		this.inboundRouteID = flowType;
	}

	public String getTargets() {
		return targets;
	}

	public void setTargets(String targets) {
		this.targets = targets;
	}

	public Long getRetweetStatusID() {
		return retweetStatusID;
	}

	public void setRetweetStatusID(Long retweetStatusID) {
		this.retweetStatusID = retweetStatusID;
	}

	


	public Boolean getDocumentsRequired() {
		return documentsRequired;
	}

	public void setDocumentsRequired(Boolean documentsRequired) {
		this.documentsRequired = documentsRequired;
	}

	public String getInitialfolder() {
		return initialfolder;
	}

	public void setInitialfolder(String initialfolder) {
		this.initialfolder = initialfolder;
	}

	public ICompassStatusView getRetweetStatus() {
		if(retweetStatus==null && this.getRetweetStatusID()!=null){
			CompassStatusModel retweet = new CompassStatusModel();
			this.initModel((IBasicView)retweet);
			retweet.setID(this.getRetweetStatusID());
			try{
				if(retweet.selfSelect())
					retweetStatus=retweet;
			}
			catch(Exception ex){
				LoggerUtil.DEBUG(ex);
			}
		}
		return retweetStatus;
	}

	public void setRetweetStatus(ICompassStatusView retweetStatus) {
		this.retweetStatus = retweetStatus;
	}
	
	
	

	@Override
	public Collection<IBasicView> getChildren() {
		if(children==null && this.getRetweetStatus()!=null){
			children=new ArrayList<IBasicView>();
			children.add(this.getRetweetStatus());
		}	
		return super.getChildren();
	}

	public Long getFlowID() {
		return flowID;
	}

	public void setFlowID(Long flowID) {
		this.flowID = flowID;
	}

	public Long getInboundEventID() {
		return inboundEventID;
	}

	public void setInboundEventID(Long inboundEventID) {
		this.inboundEventID = inboundEventID;
	}

	public Long getInboundStepID() {
		return inboundStepID;
	}

	public void setInboundStepID(Long inboundStepID) {
		this.inboundStepID = inboundStepID;
	}

	public Long getOutboundEventID() {
		return outboundEventID;
	}

	public void setOutboundEventID(Long outboundEventID) {
		this.outboundEventID = outboundEventID;
	}

	@Override
	public List<Map<String, Object>> generateBehaviorStructures(int type) {
		//System.out.println("generateBehaviorStructures: "+type);
		if(type==BEHAVIORSTRUCTURE_EDITFORM){
			List<Map<String, Object>> structures=new ArrayList<Map<String, Object>>();
			
			structures.add(this.generateBehaviorStructure(ATTR_ID, true));
			structures.add(this.generateBehaviorStructure(ATTR_METAID, true));
			structures.add(this.generateBehaviorStructure(ATTR_INBOUNDROUTEID, true));
			structures.add(this.generateBehaviorStructureHidden(ATTR_FLOWID));
			structures.add(this.generateBehaviorStructure(ATTR_TARGETS, true));
			structures.add(this.generateBehaviorStructure(ATTR_SHORTTEXT, true));
			structures.add(this.generateBehaviorStructure(ATTR_LONGTEXT, true));
			structures.add(this.generateBehaviorStructure(SYNC_INITIALFOLDER, false));
			//structures.add(this.generateBehaviorStructure(SYNC_DOCUMENTSREQUIRED, false));
			
			return structures;
		}
		if(type==BEHAVIORSTRUCTURE_STATUSREPLY){
			List<Map<String, Object>> structures=new ArrayList<Map<String, Object>>();
			
			structures.add(this.generateBehaviorStructure(ATTR_ID, true));
			structures.add(this.generateBehaviorStructure(ATTR_METAID, true));
			structures.add(this.generateBehaviorStructureHidden(ATTR_INBOUNDROUTEID));
			structures.add(this.generateBehaviorStructure(ATTR_TARGETS, false));
			structures.add(this.generateBehaviorStructure(ATTR_SHORTTEXT, false));
			structures.add(this.generateBehaviorStructure(ATTR_LONGTEXT, true));
			structures.add(this.generateBehaviorStructureHidden(ATTR_RETWEETEDSTATUSID));
			structures.add(this.generateBehaviorStructureHidden(ATTR_FLOWID));
			structures.add(this.generateBehaviorStructure(ATTR_INBOUNDEVENTID, false));
			//structures.add(this.generateBehaviorStructure(SYNC_INITIALFOLDER, false));
			//structures.add(this.generateBehaviorStructure(SYNC_DOCUMENTSREQUIRED, false));
			
			return structures;
		}
		if(type==BEHAVIORSTRUCTURE_STATUSFORWARD){
			List<Map<String, Object>> structures=new ArrayList<Map<String, Object>>();
			
			structures.add(this.generateBehaviorStructure(ATTR_ID, true));
			structures.add(this.generateBehaviorStructure(ATTR_METAID, true));
			structures.add(this.generateBehaviorStructure(ATTR_INBOUNDROUTEID, true));
			structures.add(this.generateBehaviorStructureHidden(ATTR_FLOWID));
			structures.add(this.generateBehaviorStructure(ATTR_TARGETS, false));
			structures.add(this.generateBehaviorStructure(ATTR_SHORTTEXT, false));
			structures.add(this.generateBehaviorStructure(ATTR_LONGTEXT, true));
			structures.add(this.generateBehaviorStructureHidden(ATTR_RETWEETEDSTATUSID));
			structures.add(this.generateBehaviorStructure(ATTR_INBOUNDEVENTID, false));
			//structures.add(this.generateBehaviorStructure(SYNC_INITIALFOLDER, false));
			//structures.add(this.generateBehaviorStructure(SYNC_DOCUMENTSREQUIRED, false));
			
			return structures;
		}
		return super.generateBehaviorStructures(type);
	}



	@Override
	public void selfExecute(String actioncode) throws BasicException {
		//System.out.println("actioncode "+actioncode);
		if(ACTIONCODE_INITFOLDER.equals(actioncode))
			this.selfInitFolder();
		super.selfExecute(actioncode);
	}
	


	public  void selfInitFolder(){
		System.out.println("selfInitFolder "+this.getInitialfolder());
	}
	


	@Override
	public void selfCreate() throws BasicException {
		//System.out.println("create status for "+this.getInboundRouteID());
		//System.out.println("getInboundEventID "+this.getInboundEventID());
		if(this.getInboundRouteID()==null)
			return;
		try{
			//System.out.println("sessionprofile "+this.getSessionProfile().getSequenceType());
			if(this.getIconLink()==null 
					&& this.getInboundRouteID()!=null){
				IWolfRouteView route = (IWolfRouteView)BeanFactory.getCurrentFactory().getModelFactory().getModel(IWolfRouteView.META_ID);
				this.initModel((IBasicView)route);
				((IWolfRouteManip)route).setID(this.getInboundRouteID());
				if(route.selfSelect())
					this.setIconLink(route.getIconLink());
				//System.out.println("icon link "+route.getIconLink());
			}
			
			if(this.getCreateUserID()==null){
				this.setCreateUserID(this.getSessionProfile().getUser().getID());
			}
			
			super.selfCreate();
			
			if(Boolean.TRUE.equals(this.getDocumentsRequired()) 
					&& this.getInitialfolder()!=null){
				this.initDocuments();				
			}
			
			if(this.getTargets()!=null){
				String targetusers[] = null;
				if(this.getTargets().contains(";"))
					targetusers = this.getTargets().split(";");
				else
					targetusers = new String[]{this.getTargets()};
				
				//System.out.println("targetusers "+targetusers);
				if(targetusers!=null 
						&& targetusers.length>0){
					if(this.getInboundEventID()==null){
						this.initFlow(targetusers);				
					}
					else{
						this.triggerEvent(targetusers);

					}
				}
			}
		}
		catch(Exception ex){
			LoggerUtil.DEBUG(ex);
		}
		//System.out.println("create id "+this.getID());
	}
	
	protected  void initFlow(String targetusers[])throws Exception{
		AddFlowFunc afunc=new AddFlowFunc();
		this.initFunction(afunc);
		for(String target: targetusers){
			UserModel user = new UserModel();
			this.initModel((IBasicView)user);
			user.setName(target);
			if(user.selfSelect()){
				//user.selfCreate();
				//System.out.println("find target "+target+" ID "+user.getID());
				IWolfFlowView flow = afunc.function(
						this.getShortText()
						, this.getInboundRouteID()
						, user.getID()
						, ""+this.getID());
				this.setFlowID(flow.getID());
				this.selfModify();
				
				//System.out.println("&&&&&&&&&&&&&&&&&& this.getInitialfolder() "+this.getInitialfolder());
				//System.out.println("&&&&&&&&&&&&&&&&&& this.getDocumentsRequired() "+this.getDocumentsRequired());
				//CSS
				//check if CSS. If yes, copy the files; If no, add a record for future copy.
				if(Boolean.TRUE.equals(this.getDocumentsRequired())){
					
					//initial folder transfer
					//this.tempFolderTransfer();
					
					this.transferDocuments(user);					
				}
				
			}
			else
				LoggerUtil.WARNING("User of "+target+" not found!!!");//TODO:
			
		}
		MailNotificationFunc mfunc=new MailNotificationFunc();
		this.initFunction(mfunc);
		mfunc.function(targets, this.getShortText(), this.getLongText());
	}
	protected  void triggerEvent(String targetusers[])throws Exception{
		TriggerEventFunc tfunc=new TriggerEventFunc();
		this.initFunction(tfunc);
		for(String target: targetusers){
			UserModel user = new UserModel();
			this.initModel((IBasicView)user);
			user.setName(target);
			if(user.selfSelect()){
				//user.selfCreate();
				//System.out.println("find target "+target+" ID "+user.getID());
				tfunc.function(this.getInboundEventID(), user.getID(), this.getInboundRouteID(), ""+this.getID());
				//System.out.println("this.getDocumentsRequired() "+this.getDocumentsRequired());
				if(Boolean.TRUE.equals(this.getDocumentsRequired())){
					this.transferDocuments(user);					
				}
				
			}
			else
				LoggerUtil.WARNING("User of "+target+" not found!!!");//TODO:
			
		}
	}
	protected  void tempFolderTransfer(){
		String parentfolder = this.getShortText()+ this.getID();
		
		String receiverfolder = generateReceivedFolder(
				generateUserFolder(parentfolder, this.getSessionProfile().getUser())
			);

		this.copyDocuments(
				((ICompassPortfolioView)this.getSessionProfile().getPortfolio()).getCodiskAccountID()
				, this.getSessionProfile().getIdentity()
				, this.getInitialfolder()
				, ((ICompassPortfolioView)this.getSessionProfile().getPortfolio()).getCodiskAccountID()
				, this.getSessionProfile().getIdentity()
				, receiverfolder
				, true);
	}
	protected  void initDocuments(){
		String senderfolder = this.getInitialfolder();
		
		String parentfolder = this.generateParentFolder();
		String receiverfolder = generateSentFolder (
				generateUserFolder(parentfolder, this.getSessionProfile().getUser())
			);
		this.moveDocuments(this.getSessionProfile().getUser().getID(), senderfolder, true, receiverfolder, true);
	}
	protected  void  transferDocuments(IUserView receiver){
		System.out.println("&&&&&&&&&&     transferDocuments ");
		String parentfolder = this.generateParentFolder();
		
		String senderfolder = generateSentFolder (
					generateUserFolder(parentfolder, this.getSessionProfile().getUser())
				);
		
		try{
			IIdentityView identity = (IIdentityView)BeanFactory.getCurrentFactory().getModelFactory().getModel(IIdentityMeta.META_ID);
			((IIdentityManip)identity).setUserID(receiver.getID());
			if(identity.selfSelect()){
				//existed
				System.out.println("receiver "+receiver.getID());
				ICompassPortfolioView portfolio = (ICompassPortfolioView)BeanFactory.getCurrentFactory().getModelFactory().getModel(ICompassPortfolioMeta.META_ID);
				this.initModel(portfolio);
				((ICompassPortfolioManip)portfolio).setAdminUserID(receiver.getID());
				//System.out.println("portfolio.getAutomiaticDownload() "+portfolio.getAutomiaticDownload());
				if(portfolio.selfSelect() 
						//&& Boolean.TRUE.equals(portfolio.getAutomiaticDownload())
						){
					String receiverfolder = generateReceivedFolder(
							generateUserFolder(parentfolder, receiver)
						);
					
					System.out.println("receiverfolder "+receiverfolder);
		
					this.copyDocuments(
							((ICompassPortfolioView)this.getSessionProfile().getPortfolio()).getCodiskAccountID()
							, this.getSessionProfile().getIdentity()
							, senderfolder
							, portfolio.getCodiskAccountID()
							, identity
							, receiverfolder
							, false);
				}
				else{
					LoggerUtil.DEBUG("portfolio may not exist! "+receiver.getID());
				}
			}
			else{
				
				//not existed
				//wait for receiver drag
			}
		}
		catch(Exception ex){
			ex.printStackTrace();
		}
		
	}
/*	protected  String generateTemporaryFolder(){
		return this.getInitialfolder();
	}*/
	protected  String generateParentFolder(){
		return this.getShortText()+ this.getID();
	}
	protected  String generateUserFolder(String parentfolder, IUserView user){
		return parentfolder + "_" + user.getShortText();
	}
	protected  String generateSentFolder(String parentfolder){
		return parentfolder;//+ "/" +"SENT";
	}
	protected  String generateReceivedFolder(String parentfolder){
		return parentfolder;//+ "/" +"RECEIVED";
	}
	protected  void  moveDocuments(Long owneridentityid, String srcfolder, boolean clearsrc, String destfolder, boolean newdest){
		
		//internal move
		//CSSAccountFunc func=new CSSAccountFunc();
		//this.initFunction(func);
		try{
			//ICodiskAccountView account = func.function(owneridentityid);
			if(((ICompassPortfolioView)this.getSessionProfile().getPortfolio()).getCodiskAccountID()!=null){
				ICodiskAdapter adapter = CodiskAdapterFactory.getAdapter(((ICompassPortfolioView)this.getSessionProfile().getPortfolio()).getCodiskAccountID());
				
				
				//System.out.println("move folder "+srcfolder+" to "+destfolder);
				adapter.movedir(srcfolder, destfolder);
				
			}
		}
		catch(Exception ex){
			LoggerUtil.DEBUG(ex);
		}
		
	}
	protected  void  copyDocuments(Long senderAccountID, IIdentityView senderidentity, String srcfolder
			, Long receiverAccountID, IIdentityView receiveridentity, String destfolder, boolean clearsrc){
		try{
			//ICodiskAccountView account = func.function(owneridentityid);
			if(((ICompassPortfolioView)this.getSessionProfile().getPortfolio()).getCodiskAccountID()!=null){
				ICodiskAdapter adapter = CodiskAdapterFactory.getAdapter(((ICompassPortfolioView)this.getSessionProfile().getPortfolio()).getCodiskAccountID());
				
				
				System.out.println("copy folder "+srcfolder+" to "+destfolder);
				adapter.copydir(srcfolder, destfolder);
				
			}
		}
		catch(Exception ex){
			LoggerUtil.DEBUG(ex);
		}
		/*ICompassTransactionView transaction = (ICompassTransactionView)BeanFactory.getCurrentFactory().getModelFactory().getModel(ICompassTransactionMeta.META_ID);
		this.initModel(transaction);
		
		((ICompassTransactionManip)transaction).setSrcAccountID(senderAccountID);
		((ICompassTransactionManip)transaction).setSrcIdentityID(senderidentity.getID());
		((ICompassTransactionManip)transaction).setSrcIdentityName(senderidentity.getAuthname());
		((ICompassTransactionManip)transaction).setDestAccountID(receiverAccountID);
		((ICompassTransactionManip)transaction).setDestIdentityID(receiveridentity.getID());
		((ICompassTransactionManip)transaction).setSrcCloudPath(srcfolder);
		((ICompassTransactionManip)transaction).setDestCloudPath(destfolder);
		
		try{
			((ICompassTransactionManip)transaction).selfCreate();
		}
		catch(Exception ex){
			LoggerUtil.DEBUG(ex);
		}*/
	}

}
